# -*- coding: utf-8 -*-
import sys

from PyQt5.QtCore import Qt, QRectF
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *


class VerticalMeter(QWidget):
    def __init__(self, *args, **kwargs):
        # text = kwargs.pop("text", "")
        super(VerticalMeter, self).__init__(*args, **kwargs)
        self.InitUI()

    def InitUI(self):
        # 背景区域设置
        self.bgWidth = 80  # 控件显示区宽度
        self.bgHeight = 200  # 控件显示区高度
        self.bgColor = QColor(55, 55, 55, 100)  # 背景色
        self.bgBorderColor = QColor(200, 200, 200, 200)  # 边框颜色

        # 条形色块绘制
        self.region1Color = QColor(200, 200, 200, 200)  # 灰色 着陆决断高度
        self.region2Color = QColor(0, 255, 0, 200)  # 绿色 正常飞行高度区间
        self.region3Color = QColor(255, 0, 0, 200)  # 红色 最大升限高度
        self.lateralDirection = 0  # 0-色块在左侧 1-色块在右侧
        self.ColorBarWidthRatio = 0.1  # 条形色块宽度占据比例

        # 指针滑块属性
        self.pointerColor = QColor(0, 0, 0, 255)  # 指针背景色
        self.pointerWidthRatio = 0.52  # 指针宽度 0 ~ 1
        self.pointerHeightRatio = 0.1  # 指针高度 0 ~ 1
        self.pointerOffsetX = -0.01  # X轴偏移 向右为正 0~1
        self.pointerOffsetY = 0  # Y轴偏移 向上为正 0~1
        # 设置字符
        self.font = QFont("Noto Sans S Chinese Bold", 12)  # 读数文字字体
        # self.font.setBold(True)
        self.pointerTextColor = QColor(255, 255, 255, 255)  # 刻度值文字显示颜色

        # # 目标滑块属性
        # self.targetColor = QColor(248, 161, 164, 255)  # 指针背景色
        # self.targetBorderColor = QColor(19, 133, 53, 0)  # 指针背景色
        # self.targetWidthRatio = 0.10  # 指针宽度 0 ~ 1
        # self.targetHeightRatio = 0.15  # 指针高度 0 ~ 1
        # self.targetOffsetX = 0  # X轴偏移 向右为正 0~1
        # self.targetOffsetY = 0  # Y轴偏移 向上为正 0~1

        # 刻度尺属性
        self.scaleColor = QColor(255, 255, 255, 255)  # 刻度线颜色
        self.scaleUnit = 10  # 刻度单位 刻度线之间的间隔值
        self.region2MinValue = 20  # 20以下以region1Color显示
        self.region2MaxValue = 70  # 50以上以region3Color显示
        self.currentValue = 0  # 当前标识值
        self.viewLength = 100  # 可见区域高度
        self.startValue = self.currentValue - self.viewLength / 2  # 起始位置对应取值
        self.endValue = self.startValue + self.viewLength  # 终止位置对应取值
        self.scaleFont = QFont("Noto Sans S Chinese Bold", 12)  # 读数文字字体
        self.scaleLineStartPos = 0.75  # 刻度线起始位置（0 ~ 1）
        self.scaleLineEndPos = 1  # 刻度线终止位置（0 ~ 1）

        self.maxValue = 500  # 最大值 标尺显示最大值
        self.minValue = 0  # 最小值 标尺显示最小值
        self.startRegionRatio = 0.05  # 区块1占据比例
        self.midRegionRatio = 0.8  # 区块2占据比例
        self.endRegionRatio = 0.15  # 区块3占据比例

        # self.InitUI()  # 界面绘制交给InitUi方法
        # 目标指示标识相关属性
        self.target_x_start = -0.1
        self.target_x_end = 0.5
        self.target1_value = 110
        self.target2_value = 100
        self.target1_text = "V1"
        self.target2_text = "V2"
        self.target1_pen = QPen(QColor(255, 0, 0), 8, Qt.SolidLine)
        self.target2_pen = QPen(QColor(255, 0, 0), 8, Qt.SolidLine)
        self.target_text_pen = QPen(QColor(255, 0, 0), 1, Qt.SolidLine)
        self.target_text_font = QFont("Noto Sans S Chinese Bold", 14)  # 读数文字字体
        # 窗口初始化
        self.setMinimumSize(self.bgWidth, self.bgHeight)

    # 设置取值接口
    def setValue(self, value):
        self.currentValue = value
        self.startValue = self.currentValue - self.viewLength / 2  # 起始位置对应取值
        self.endValue = self.startValue + self.viewLength  # 终止位置对应取值
        self.update()

    def setTargetValue(self, targe1, targe2):
        self.target1_value = targe1
        self.target2_value = targe2
        self.update()

    def paintEvent(self, event):
        width = self.width()
        height = self.height()

        painter = QPainter(self)  # 初始化painter
        painter.translate(width / 2, height / 2)  # 坐标轴变换，调用translate()将坐标原点平移至窗口中心

        # 坐标刻度自适应
        # side = min(width, height)
        # painter.scale(side / 200.0, side / 200.0)
        self.bgWidth = width
        self.bgHeight = height
        # 本项目中将坐标缩小为side/200倍，即画出length=10的直线，其实际长度应为10*(side/200)。
        painter.setClipRect(QRectF(-self.bgWidth / 2, -self.bgHeight / 2, self.bgWidth, self.bgHeight),
                            Qt.IntersectClip)
        # 启用反锯齿，使画出的曲线更平滑
        painter.setRenderHints(QPainter.Antialiasing | QPainter.TextAntialiasing)
        painter.begin(self)

        # 开始画图
        self.drawBackGround(painter)
        self.drawColorBar(painter)
        self.drawTargetIndicator(painter)
        self.drawScaleLine(painter)
        self.drawPointerIndicator(painter)

        painter.end()

    def drawBackGround(self, painter):  # 背景区域绘制
        painter.save()
        painter.setPen(Qt.NoPen)
        brush = QBrush(Qt.SolidPattern)
        brush.setColor(self.bgColor)
        painter.setBrush(brush)
        painter.drawRect(-self.bgWidth / 2, -self.bgHeight / 2, self.bgWidth, self.bgHeight)

        pen = QPen(Qt.blue, 1, Qt.SolidLine)
        pen.setColor(self.bgBorderColor)
        painter.setPen(pen)
        painter.drawLine(-self.bgWidth / 2, -self.bgHeight / 2, self.bgWidth / 2, -self.bgHeight / 2)
        painter.drawLine(self.bgWidth / 2, -self.bgHeight / 2, self.bgWidth / 2, self.bgHeight / 2)
        painter.drawLine(self.bgWidth / 2, self.bgHeight / 2, -self.bgWidth / 2, self.bgHeight / 2)
        painter.drawLine(-self.bgWidth / 2, self.bgHeight / 2, -self.bgWidth / 2, -self.bgHeight / 2)

        painter.restore()

    def drawColorBar(self, painter):  # 条形区域绘制
        painter.save()  # save()保存当前坐标系
        painter.setPen(Qt.NoPen)

        if self.region2MinValue > self.startValue:
            region1_height = (self.region2MinValue - self.startValue) / self.viewLength * self.bgHeight
            region1_height = min(self.bgHeight, int(region1_height))
        else:
            region1_height = 0

        if self.region2MaxValue < self.endValue:
            region3_height = (self.endValue - self.region2MaxValue) / self.viewLength * self.bgHeight
            region3_height = min(self.bgHeight, int(region3_height))
        else:
            region3_height = 0

        region2_height = self.bgHeight - region3_height - region1_height

        rg = QLinearGradient(-self.bgWidth / 2, self.bgHeight / 2, self.bgWidth / 2, self.bgHeight / 2)
        ratio = 1 - self.ColorBarWidthRatio

        # 绘制底部色块
        # 设置渐变色
        if self.lateralDirection < 1:
            rg.setColorAt(0, Qt.transparent)  # 透明色
            rg.setColorAt(ratio, Qt.transparent)
            rg.setColorAt(ratio + 0.02, self.region1Color)
            rg.setColorAt(1, self.region1Color)
        else:
            rg.setColorAt(0, self.region1Color)  # 透明色
            rg.setColorAt(1 - ratio, self.region1Color)
            rg.setColorAt(1 - ratio + 0.02, Qt.transparent)
            rg.setColorAt(1, Qt.transparent)
        # 绘制矩形
        painter.setBrush(rg)
        painter.drawRect(-self.bgWidth / 2, self.bgHeight / 2 - region1_height, self.bgWidth, region1_height)

        # # 绘制中间色块
        # 设置渐变色
        if self.lateralDirection < 1:
            rg.setColorAt(0, Qt.transparent)  # 透明色
            rg.setColorAt(ratio, Qt.transparent)
            rg.setColorAt(ratio + 0.02, self.region2Color)
            rg.setColorAt(1, self.region2Color)
        else:
            rg.setColorAt(0, self.region2Color)  # 透明色
            rg.setColorAt(1 - ratio, self.region2Color)
            rg.setColorAt(1 - ratio + 0.02, Qt.transparent)
            rg.setColorAt(1, Qt.transparent)
        # 绘制矩形
        painter.setBrush(rg)
        painter.drawRect(-self.bgWidth / 2, self.bgHeight / 2 - region1_height - region2_height, self.bgWidth,
                         region2_height)
        # 绘制最上层色块
        # 设置渐变色
        if self.lateralDirection < 1:
            rg.setColorAt(0, Qt.transparent)  # 透明色
            rg.setColorAt(ratio, Qt.transparent)
            rg.setColorAt(ratio + 0.02, self.region3Color)
            rg.setColorAt(1, self.region3Color)
        else:
            rg.setColorAt(0, self.region3Color)  # 透明色
            rg.setColorAt(1 - ratio, self.region3Color)
            rg.setColorAt(1 - ratio + 0.02, Qt.transparent)
            rg.setColorAt(1, Qt.transparent)
        # 绘制矩形
        painter.setBrush(rg)
        painter.drawRect(-self.bgWidth / 2, self.bgHeight / 2 - region1_height - region2_height - region3_height,
                         self.bgWidth,
                         region3_height)

        painter.restore()  # restore()恢复坐标系

    def drawPointerIndicator(self, painter):
        painter.save()
        painter.setPen(Qt.NoPen)
        painter.setBrush(self.pointerColor)

        # 绘制指针
        pointer_width = self.pointerWidthRatio * self.bgWidth
        pointer_height = self.pointerHeightRatio * self.bgHeight
        pointer_offset_x = (0.5 - self.pointerWidthRatio + self.pointerOffsetX) * self.bgWidth  # X轴偏移 向右为正
        pointer_offset_y = self.pointerOffsetY * self.bgHeight  # Y轴偏移 向上为正
        # # (-5, 0), (0, -8), (5, 0)和（0, radius) 四个点绘出指针形状
        # 绘制多边形做指针
        pts = QPolygon()
        # (0,-height/2)            (width-height*0.618,-height/2)
        # |------------------------\
        # |                         \
        # |                          \  (widht, 0)
        # |                          /
        # |                         /
        # |------------------------/
        # (0,height/2)             (widht-height*0.618, height/2)
        if self.lateralDirection < 1:
            pts.setPoints(0, int(-pointer_height / 2),
                          pointer_width - pointer_height * 0.618, -pointer_height / 2,
                          pointer_width, 0,
                          pointer_width - pointer_height * 0.618, pointer_height / 2,
                          0, pointer_height / 2)
            painter.translate(pointer_offset_x, -pointer_offset_y)
        else:
            # (height*0.618-width,-height/2)    (0,-height/2)
            #               /------------------------|
            #              /                         |
            #             /                          |
            # (-widht, 0) \                          |
            #              \                         |
            #               \------------------------|
            # (height*0.618-width,height/2)     (0, height/2)
            pts.setPoints(0, int(-pointer_height / 2),
                          -pointer_width + pointer_height * 0.618, -pointer_height / 2,
                          -pointer_width, 0,
                          -pointer_width + pointer_height * 0.618, pointer_height / 2,
                          0, pointer_height / 2)
            painter.translate(-pointer_offset_x, -pointer_offset_y)

        painter.drawConvexPolygon(pts)

        painter.translate(pointer_offset_x, 0)  # 坐标回到中心点
        painter.setFont(self.font)
        painter.setPen(self.pointerTextColor)  # 设置文字颜色
        strValue = '%3d' % int(self.currentValue)
        textWidth = self.fontMetrics().width("%3d" % int(self.maxValue)) * 1.5

        # 显示当前刻度值
        if self.lateralDirection < 1:
            # 指向右侧
            rectf = QRectF(-pointer_offset_x, -pointer_height / 2, pointer_width, pointer_height)
        else:
            # 指向左侧
            rectf = QRectF(textWidth - pointer_width, -pointer_height / 2, pointer_width, pointer_height)

        painter.drawText(rectf, Qt.AlignVCenter | Qt.AlignCenter, strValue)
        painter.restore()

    def drawTargetIndicator(self, painter):  # 绘制目标标识形状
        painter.save()

        # 绘制指针
        x_start = self.target_x_start * self.bgWidth
        x_end = self.target_x_end * self.bgWidth
        target1_value = self.target1_value
        target2_value = self.target2_value
        target1_text = self.target1_text
        target2_text = self.target2_text

        target1_pen = self.target1_pen
        target2_pen = self.target2_pen
        target_text_pen = self.target_text_pen
        target_text_font = self.target_text_font

        if self.lateralDirection < 1:
            y1 = self.bgHeight / 2 - (target1_value - self.startValue) / self.viewLength * self.bgHeight
            painter.setPen(target1_pen)
            painter.drawLine(x_start, y1, x_end, y1)  # 画出刻度线
            y2 = self.bgHeight / 2 - (target2_value - self.startValue) / self.viewLength * self.bgHeight
            painter.setPen(target2_pen)
            painter.drawLine(x_start, y2, x_end, y2)  # 画出刻度线

            # draw text
            painter.setPen(target_text_pen)
            textWidth = self.fontMetrics().width(target1_text) * 1.5
            textHeight = self.fontMetrics().height()
            painter.setFont(target_text_font)
            rectf = QRectF(x_start - textWidth * 1.6, y1 - textHeight / 2, textWidth * 1.5, textHeight)
            painter.drawText(rectf, Qt.AlignVCenter | Qt.AlignRight, target1_text)

            textWidth = self.fontMetrics().width(target2_text) * 1.5
            textHeight = self.fontMetrics().height()
            painter.setFont(target_text_font)
            rectf = QRectF(x_start - textWidth * 1.6, y2 - textHeight / 2, textWidth * 1.5, textHeight)
            painter.drawText(rectf, Qt.AlignVCenter | Qt.AlignRight, target2_text)

        else:
            y1 = self.bgHeight / 2 - (target1_value - self.startValue) / self.viewLength * self.bgHeight
            painter.setPen(target1_pen)
            painter.drawLine(-x_start, y1, -x_end, y1)  # 画出刻度线
            y2 = self.bgHeight / 2 - (target2_value - self.startValue) / self.viewLength * self.bgHeight
            painter.setPen(target2_pen)
            painter.drawLine(-x_start, y2, -x_end, y2)  # 画出刻度线

            # draw text
            painter.setPen(target_text_pen)
            textWidth = self.fontMetrics().width(target1_text) * 1.5
            textHeight = self.fontMetrics().height()
            painter.setFont(target_text_font)
            rectf = QRectF(-x_start, y1 - textHeight / 2, textWidth * 1.5, textHeight)
            painter.drawText(rectf, Qt.AlignVCenter | Qt.AlignRight, target1_text)

            textWidth = self.fontMetrics().width(target2_text) * 1.5
            textHeight = self.fontMetrics().height()
            painter.setFont(target_text_font)
            rectf = QRectF(-x_start, y2 - textHeight / 2, textWidth * 1.5, textHeight)
            painter.drawText(rectf, Qt.AlignVCenter | Qt.AlignRight, target2_text)

        painter.restore()

    def drawScaleLine(self, painter):  # 画出刻度和刻度文字
        painter.save()
        # 绘制刻度线
        # 计算从最低点开始第一个刻度所对应的取值
        if self.lateralDirection < 1:
            left_offset = (self.scaleLineStartPos - 0.5) * self.bgWidth
            right_offset = (self.scaleLineEndPos - 0.5) * self.bgWidth
        else:
            left_offset = (0.5 - self.scaleLineStartPos) * self.bgWidth
            right_offset = (0.5 - self.scaleLineEndPos) * self.bgWidth

        color = self.scaleColor
        painter.setPen(QPen(color, 1, Qt.SolidLine))
        textWidth = self.fontMetrics().width("%3d" % int(self.maxValue)) * 1.5
        textHeight = self.fontMetrics().height()
        painter.setFont(self.scaleFont)
        # painter.setPen(self.pointerTextColor)  # 设置文字颜色

        tmpScaleValue = (int(self.startValue / self.scaleUnit) - 1) * self.scaleUnit
        while tmpScaleValue < self.endValue + self.scaleUnit:
            # 画刻度线
            y = self.bgHeight / 2 - (tmpScaleValue - self.startValue) / self.viewLength * self.bgHeight
            painter.drawLine(left_offset, y, right_offset, y)  # 画出刻度线

            # 画刻度文字
            if self.minValue <= tmpScaleValue <= self.maxValue:
                strValue = "%3d" % int(tmpScaleValue)
                if self.lateralDirection < 1:
                    rectf = QRectF(left_offset - textWidth * 1.6, y - textHeight / 2, textWidth * 1.5, textHeight)
                    painter.drawText(rectf, Qt.AlignVCenter | Qt.AlignRight, strValue)
                else:
                    rectf = QRectF(left_offset + 0.1 * textWidth, y - textHeight / 2, textWidth * 1.5, textHeight)
                    painter.drawText(rectf, Qt.AlignVCenter | Qt.AlignLeft, strValue)

            tmpScaleValue = tmpScaleValue + self.scaleUnit

        painter.restore()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = VerticalMeter()
    # demo.InitUI()
    demo.show()
    demo.setValue(80)  # 设置指针指向
    # demo.lateralDirection = 1
    # demo.setTitle("Title_____")  # 设置图标题
    sys.exit(app.exec_())
